#include <mips/regdef.h>
#include <sys/syscall.h>

	.data
	.align	2
	.type	map1, @object
	.size	map1, 1024
map1:
	.word	0
	.word	1
	.word	2
	.word	3
	.word	4
	.word	5
	.word	6
	.word	7
	.word	8
	.word	9
	.word	10
	.word	11
	.word	12
	.word	13
	.word	14
	.word	15
	.word	16
	.word	17
	.word	18
	.word	19
	.word	20
	.word	21
	.word	22
	.word	23
	.word	24
	.word	25
	.word	26
	.word	27
	.word	28
	.word	29
	.word	30
	.word	31
	.word	32
	.word	33
	.word	34
	.word	35
	.word	36
	.word	37
	.word	38
	.word	39
	.word	40
	.word	41
	.word	42
	.word	43
	.word	44
	.word	45
	.word	46
	.word	47
	.word	48
	.word	49
	.word	50
	.word	51
	.word	52
	.word	53
	.word	54
	.word	55
	.word	56
	.word	57
	.word	58
	.word	59
	.word	60
	.word	61
	.word	62
	.word	63
	.word	64
	.word	65
	.word	66
	.word	67
	.word	68
	.word	69
	.word	70
	.word	71
	.word	72
	.word	73
	.word	74
	.word	75
	.word	76
	.word	77
	.word	78
	.word	79
	.word	80
	.word	81
	.word	82
	.word	83
	.word	84
	.word	85
	.word	86
	.word	87
	.word	88
	.word	89
	.word	90
	.word	91
	.word	92
	.word	93
	.word	94
	.word	95
	.word	96
	.word	97
	.word	98
	.word	99
	.word	100
	.word	101
	.word	102
	.word	103
	.word	104
	.word	105
	.word	106
	.word	107
	.word	108
	.word	109
	.word	110
	.word	111
	.word	112
	.word	113
	.word	114
	.word	115
	.word	116
	.word	117
	.word	118
	.word	119
	.word	120
	.word	121
	.word	122
	.word	123
	.word	124
	.word	125
	.word	126
	.word	127
	.word	128
	.word	129
	.word	130
	.word	131
	.word	132
	.word	133
	.word	134
	.word	135
	.word	136
	.word	137
	.word	138
	.word	139
	.word	140
	.word	141
	.word	142
	.word	143
	.word	144
	.word	145
	.word	146
	.word	147
	.word	148
	.word	149
	.word	150
	.word	151
	.word	152
	.word	153
	.word	154
	.word	155
	.word	156
	.word	157
	.word	158
	.word	159
	.word	160
	.word	161
	.word	162
	.word	163
	.word	164
	.word	165
	.word	166
	.word	167
	.word	168
	.word	169
	.word	170
	.word	171
	.word	172
	.word	173
	.word	174
	.word	175
	.word	176
	.word	177
	.word	178
	.word	179
	.word	180
	.word	181
	.word	182
	.word	183
	.word	184
	.word	185
	.word	186
	.word	187
	.word	188
	.word	189
	.word	190
	.word	191
	.word	192
	.word	193
	.word	194
	.word	195
	.word	196
	.word	197
	.word	198
	.word	199
	.word	200
	.word	201
	.word	202
	.word	203
	.word	204
	.word	205
	.word	206
	.word	207
	.word	208
	.word	209
	.word	210
	.word	211
	.word	212
	.word	213
	.word	214
	.word	215
	.word	216
	.word	217
	.word	218
	.word	219
	.word	220
	.word	221
	.word	222
	.word	223
	.word	224
	.word	225
	.word	226
	.word	227
	.word	228
	.word	229
	.word	230
	.word	231
	.word	232
	.word	233
	.word	234
	.word	235
	.word	236
	.word	237
	.word	238
	.word	239
	.word	240
	.word	241
	.word	242
	.word	243
	.word	244
	.word	245
	.word	246
	.word	247
	.word	248
	.word	249
	.word	250
	.word	251
	.word	252
	.word	253
	.word	254
	.word	255

	.local	map2
	.comm	map2,1024,4

#----------DEFINICION DE LOS METODOS--------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.globl	tr_ds
	.ent	tr_ds
tr_ds:
# Creacion del stack frame
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)

	move	$fp, sp

# Guarda el parametro en el stack
	sw	a0, 40($fp)		# set1
	sw	a1, 44($fp)		# set2

# setup(map1, set1, 0)
	la	a0, map1
	lw 	a1, 40($fp)
	li 	a2, 0
	jal setup

# setup(map2, set2, 0)
	la	a0, map2
	lw 	a1, 44($fp)
	li 	a2, 0
	jal setup

	lw	t0, OOBCH		# lastch = OOBCH
	sw	t0, 20($fp)
for_ds:
	jal mygetchar
	beq	v0, 256, ret_ds         # Si es EOF sale del for

	lw	t0, 20($fp)		# lastch
	sw	v0, 20($fp)
	mul     t1, v0, 4               # ch

	la	t2, map1
	add	t2, t2, t1
	lw	t3, 0(t2)		# map1[ch]

	bnez 	t3, for_ds		# Si map1[ch] != null, ir al siguiente paso del for

	la	t4, map2
	add	t4, t4, t1
	lw	t5, 0(t4)		# map2[ch]

	beqz 	t5, imprimir_ds		# Si map2[ch] == null, imprimir

	beq 	t0, v0, for_ds		# Si lastch == ch, ir al siguiente paso del for.

imprimir_ds:
	
	lw 	a0, 20($fp)
	jal myputchar

	b for_ds

ret_ds:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra,  32(sp)
	lw	$fp, 28(sp)

	addiu	sp, sp, 40
	jr	ra


	.end	tr_ds
#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.globl	tr_d
	.ent	tr_d
tr_d:
# Creacion del stack frame
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)

	move	$fp, sp

# Guarda el parametro en el stack
	sw	a0, 40($fp)		# char *set1

# setup(map1, set1, 0)
	la	a0, map1
	lw 	a1, 40($fp)
	li 	a2, 0
	jal setup

while:
	jal	mygetchar
	sw	v0, 16($fp)		# ch = mygetchar()
# (ch = mygetchar()) != EOF
	beq	v0, 256, ret_d

	mul	t1, v0, 4

	la	t2, map1
	addu    t2, t2, t1
	lw	t3, 0(t2)		# map1[ch]

# 'if (!map1[ch])
	bnez	t3, while

	lw	a0, 16($fp)
	jal myputchar

	b while

ret_d:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra,  32(sp)
	lw	$fp, 28(sp)

	addiu	sp, sp, 40
	jr	ra

	.end	tr_d

#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.globl	tr_s1
	.ent	tr_s1
tr_s1:
# Creacion del stack frame
	.frame	$fp, 48, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 48
	.cprestore	32

	sw	ra,  40(sp)
	sw	$fp, 36(sp)

	move	$fp, sp

# Guarda el parametro en el stack
	sw	a0, 48($fp)		#set1

# setup(map1, set1, 0)
	la	a0, map1
	lw 	a1, 48($fp)
	li 	a2, 0
	jal setup

	lw	t0, OOBCH		# lastch = OOBCH
	sw	t0, 28($fp)		# lastch

for_s1:
	jal     mygetchar
	beq	v0, 256, ret_s1 	# Si es EOF sale del for
	lw	t4, 28($fp)		#lastch
	sw	v0, 28($fp)		#ch

	mul	t0, v0, 4

	la	t1, map1
	addu	t1, t1, t0
	lw	t2, 0(t1)		# map[ch]

	beqz    t2, imprimir_s1		# imprimir si map[ch] == null
	beq	t4, v0, for_s1		# ir al siguiente paso del for si lastch == ch
					# Si lastch != ch, imprime el caracter.

# 'if(!map1[ch] || lastch != ch)'
#		myputchar(ch);
imprimir_s1:
	lw	a0, 28($fp)

	jal myputchar

	b for_s1

ret_s1:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra,  40(sp)
	lw	$fp, 36(sp)

	addiu	sp, sp, 48
	jr	ra

	.end tr_s1

#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.globl	tr_s2
	.ent	tr_s2
tr_s2:
# Creacion del stack frame
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)

	move	$fp, sp

# Guardo los parametros
	sw	a0, 40($fp)
	sw	a1, 44($fp)

# 'if (!*set2)
	lbu	t0, 44($fp)
	beqz	t0, error_cad_vacia

# setup(map1, set1, set2)
	la	a0, map1
	lw 	a1, 40($fp)
	lw 	a2, 44($fp)
	jal setup

# setup(map2, set2, 0)
	la	a0, map2
	lw 	a1, 44($fp)
	li 	a2, 0
	jal setup

	lw	t0, OOBCH		# lastch = OOBCH
	sw	t0, 20($fp)		# lastch
for_s2:
	jal mygetchar			# v0 = mygetchar()

	beq	v0, 256, ret_s2 	# Si es EOF sale del for
	lw	t5, 20($fp)		# lastch

	#ch = map1[ch];
	la	t1, map1
	mul	t2, v0, 4
	add	t3, t1, t2
	lw	t0, 0(t3)		# ch
	sw	t0, 20($fp)		# guardo ch

	la	t1, map2
	mul	t2, t0, 4
	add	t3, t1, t2
	lw	t4, 0(t3)		# map2[ch]

	beqz	t4, imprimir_s2 	# Si map2[ch] == null, imprimir
	
	beq	t5, t0, for_s2  	# Si ch == lastch, ir al siguiente paso del for

imprimir_s2:
	lw a0, 20($fp)
	jal myputchar

	b for_s2

ret_s2:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra, 32(sp)
	lw	$fp, 28(sp)
	lw	gp, 24(sp)

	la	a0, 40(sp)

	addiu	sp, sp, 40
	j	ra

error_cad_vacia:
	li	v0, SYS_write
	li	a0, 3			# escribe en stderr
    la	a1, msg_error_cad_vacia
	li	a2, 11
	syscall

	li	v0, SYS_exit
	li	a0, 1
	syscall

	.end tr_s2
#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.globl	tr
	.ent	tr
tr:
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)

	move	$fp, sp

	sw	a0, 40($fp)		# char *set1
	sw	a1, 44($fp)		# char *set2

	#-if (!*set2)
	#	errx(1, "empty set2");
	lbu	t0, 0(a1)
	beqz	t0, error_cad_vacia

	#setup(map1, set1, set2);
	la	a0, map1
	lw 	a1, 40($fp)
	lw 	a2, 44($fp)
	jal setup

	#while ((ch = mygetchar()) != EOF)
	#	myputchar(map1[ch]);
while_tr:
	jal mygetchar
	beq	v0, 256, salir_tr        # Si es EOF sale del for

	sw	v0, 16($fp)

	#	myputchar(map1[ch]);
	la	t0, map1
	mul	t1, v0, 4
	addu	t0, t0, t1
	lw	a0,0(t0)

	jal myputchar

	b while_tr

salir_tr:
	#Destruccion del stack frame.
	move	sp, $fp
	lw	ra, 32(sp)
	lw	$fp, 28(sp)

	addiu	sp, sp, 40
	jr ra

	.end tr
#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
#-------DEFINICIONES DE AUXILIARES-------#
	.text
	.align	2
	.globl	setup #comentar esta linea despues
	.ent	setup

setup:
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)


	move	$fp, sp

	sw	a0, 40($fp)		# int* map
	sw	a1, 44($fp)		# char *set1
	sw	a2, 48($fp)		# char *set2

	#-if (!set2)
	lw	a2,48($fp)
	bnez	a2,set1_and_set2

	#memset(map, 0, NCHARS * sizeof(int));
	lw	t1, NCHARS

	lw	a0, 40($fp)
	move	t0, a0

loop_memset_zero:
	beqz	t1, set1
	sw	zero, 0(t0)
	subu	t1, t1, 1
	addu	t0, t0, 4
	j	loop_memset_zero

set1:
	lw	a0,40($fp)		# map
	lw	a1,44($fp)		# set1

#while (*set1)
while_set1:
	lbu	t0,0(a1)		# *set1
	beqz	t0,salir_setup

	#	map[(unsigned char) *set1++] = 1;
	mul	t0, t0, 4
	addu	t1, a0, t0
	li	v0, 1
	sw	v0, 0(t1)
	addu	a1, a1, 1		# set1++
	b	while_set1

set1_and_set2:
	lw	a0, 40($fp)		# map
	lw	a1, 44($fp)		# set1
	lw	a2, 48($fp)		# set2

while_set1_and_set2:
	#while (*set1 && *set2)
	lbu	t2, 0(a1)		# *set1
	lbu	t3, 0(a2)		# *set2

	beqz	t2, set_lastch
	beqz	t3, set_lastch

	#map[(unsigned char) *set1++] = *set2++;
	mul	t2, t2, 4
	addu	v0, a0, t2
	sw	t3, 0(v0)
	addu	a1, a1, 1		# set1++
	addu	a2, a2, 1		# set2++
	b	while_set1_and_set2

set_lastch:
	#lastch = *(set2 - 1);
	subu	a2, a2, 1
	lbu	t0, 0(a2)		# *set2
	sw	t0, 16($fp)

	lw	a0, 40($fp)		# map

while_set1_:
	lbu	t0, 0(a1)		# *set1
	beqz	t0, salir_setup

	#	map[(unsigned char) *set1++] = lastch;
	mul	t0, t0, 4
	addu	t1, a0, t0
	lw	v0, 16($fp)
	sw	v0, 0(t1)
	addu	a1, a1, 1		# set1++
	b	while_set1_

salir_setup:
	#Destruccion del stack frame.
	move	sp, $fp
	lw	ra, 32(sp)
	lw	$fp, 28(sp)

	lw	a0, 40(sp)
	lw	a1, 44(sp)
	lw	a2, 48(sp)

	addiu	sp, sp, 40
	jr	ra


	.end setup
#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.global
	.ent	myputchar
myputchar:
# Construccion del stack
	.frame	$fp, 40, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 40
	.cprestore	24

	sw	ra,  32(sp)
	sw	$fp, 28(sp)

	move	$fp, sp

	sw	a0, 40($fp)		# char ch

# write(file_pointer, char*, number_of_chars)
	li	v0, SYS_write
	li	a0, 1	      		# stdout
	addiu   a1, $fp, 40    		#direccion del char.
	li	a2, 1        		# numero de caracteres
	syscall

# 'if (putchar(ch) == EOF)'
# Si a3 es distinto de 0, hubo error de escritura
# Si la cantidad de caracteres leidas es dintinta
# de 1, tambien hubo error de escritura
	bnez	a3, error_escritura
	li	t0, 1
	bne	v0, t0, error_escritura

salir_put:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra, 32(sp)
	lw	$fp, 28(sp)

	addiu	sp, sp, 40
	jr	ra

error_escritura:
	li 	v0, SYS_write
	li	a0, 3
	la	a1, msg_error_escritura
	li	a2, 24
	syscall

	li	v0, SYS_exit
	li	a0, 1
	syscall

	.end myputchar

#-------------------------------------------#
#-------------------------------------------#
#-------------------------------------------#
	.text
	.align	2
	.global
	.ent	mygetchar
mygetchar:
# Construccion del stack
	.frame	$fp, 48, ra
	.set	noreorder
	.cpload	t9
	.set	reorder
	subu	sp, sp, 48
	.cprestore	32

	sw	ra,  40(sp)
	sw	$fp, 36(sp)

	move	$fp, sp

# read(file_pointer, ch, number_of_chars)
	li	v0, SYS_read
	li	a0, 0	       		#File pointer
	addiu  a1, $fp, 24 		#direccion del char.
	li	a2, 1       		#Numero de chars a leer
	syscall

# (ch = getchar()) == EOF && ferror(stdin)
# Verificamos que no haya habido error de lectura
	bne	a3, zero, error_lectura

# Si la cantidad de caracteres leidas es 0, es EOF
# Si es 1, es que leimos un caracter en memoria
# Y si es distinto a 1, es error de lectura
	beqz	v0, eof
	li	t0, 1
	bne	v0, t0, error_lectura

# return ch
	lbu    	v0, 24($fp)

	b 	salir_get

eof:
	li 	v0, 256

salir_get:
# Destruccion del stack frame
	move	sp, $fp
	lw	ra,  40(sp)
	lw	$fp, 36(sp)

	addu	sp, sp, 48

	jr	ra



error_lectura:
	li	v0, SYS_write
	li	a0, 3			# escribe en stderr
    	la	a1, msg_error_lectura
	li	a2, 24
	syscall

	li	v0, SYS_exit
	li	a0, 1
	syscall

	.end mygetchar

.rdata   # permite agragar indica que lo que sigue va en el dataseg
#--------Mensajes de Error------------#
msg_error_lectura:
	.asciiz "error reading from stdin\n"

msg_error_escritura:
	.asciiz "error writing to stdout\n"

msg_error_cad_vacia:
	.asciiz "empty set2\n"

OOBCH:
	.word	256

NCHARS:
	.word	256
